﻿# -*-coding: UTF-8 -*-
import logging

from Clover.CloverSystem import CloverSystem
from Clover.EngineSystemFactory import EngineSystemFactory
from CloverEvent.EventSignal import EventSignal


class CloverEngine:

	def __init__(self):
		self.logger = logging.getLogger("CloverEngine")
		self.event_collection = {}
		self.frame_rate = 300
		self.engine_module_table = {}
		self.engine_modules = []

	def get_engine_module_instance(self, module_name):
		return self.engine_module_table[module_name]

	def start(self):
		self.logger.info("CloverEngine start initialization")
		for system_cls in EngineSystemFactory.iter_engine_modules():
			try:
				system_instance = system_cls(self)  # type: CloverSystem
				system_cls.Instance = system_instance
				system_cls.logger = logging.getLogger(system_instance.__class__.__name__)
				self.engine_modules.append(system_instance)
				self.engine_module_table[system_cls.__name__] = system_instance
			except Exception as e:
				self.logger.error(e, exc_info=True)
				continue

	def pre_tick(self, frame_start_time):
		try:
			for engine_system in self.engine_modules:
				engine_system.pre_tick(frame_start_time)
		except Exception as e:
			self.logger.error(e, exc_info=True)

	def tick(self, delta_time):
		try:
			for engine_system in self.engine_modules:
				engine_system.tick(delta_time)
		except Exception as e:
			self.logger.error(e, exc_info=True)

	def post_tick(self, current_time, frame_time):
		try:
			for engine_system in self.engine_modules:
				engine_system.post_tick(current_time, frame_time)
		except Exception as e:
			self.logger.error(e, exc_info=True)

	def destroy(self):
		self.logger.info("CloverEngine start destroy")
		try:
			for engine_system in self.engine_modules:
				engine_system.destroy()
		except Exception as e:
			self.logger.error(e, exc_info=True)

	def register_event(self, event_name, function):
		if event_name not in self.event_collection:
			self.event_collection[event_name] = EventSignal(event_name)
		event = self.event_collection[event_name]
		event.connect(function)

	def unregister_event(self, event_name, function):
		if event_name not in self.event_collection:
			return
		event = self.event_collection[event_name]
		event.disconnect(function)

	def get_frame_rate(self):
		return self.frame_rate

	def set_frame_rate(self, frame_rate):
		frame_rate = int(max(1, frame_rate))
		self.frame_rate = frame_rate

	def register_repeat_timer(self, repeat_interval_seconds, function, *args, **kwargs):
		timer_system = self.get_engine_module_instance("TimerSystem")
		return timer_system.register_repeat_timer(repeat_interval_seconds, function, *args, **kwargs)

	def register_delay_exec(self, delay_seconds, function, *args, **kwargs):
		timer_system = self.get_engine_module_instance("TimerSystem")
		return timer_system.register_delay_exec(delay_seconds, function, *args, **kwargs)

	def cancel_timer(self, timer_id):
		timer_system = self.get_engine_module_instance("TimerSystem")
		timer_system.cancel_timer(timer_id)

	def __repr__(self):
		return "<CloverEngine>"

	def __str__(self):
		return "<CloverEngine>"
